<!DOCTYPE html>
<html>  
<head>  
  <link rel='stylesheet' href='qunit/qunit.css' type='text/css'/>  
  <script src='../editor/lib/jquery.js'></script>
  <script>
    // Mock for browser.js
    window.svgedit = {};
    svgedit.browser = {};
    svgedit.browser.supportsNativeTransformLists = function() { return false;}
  </script>
  <script type='text/javascript' src='../editor/src/svgtransformlist.js'></script>
  <script type='text/javascript' src='qunit/qunit.js'></script>  
  <script type='text/javascript'>
  $(function() {
  	// log function
  	QUnit.log = function(result, message) {
		if (window.console && window.console.log) {
			window.console.log(result +' :: '+ message);
		}
	};
	
	var svgns = 'http://www.w3.org/2000/svg';
	var svgroot = document.getElementById('svgroot');
	var svgcontent, rect, circle;
	
	var NEAR_ZERO = 5e-6; // 0.000005, Firefox fails at higher levels of precision.
	function almostEquals(a, b, msg) {
		msg = msg || (a + ' did not equal ' + b);
		ok(Math.abs(a - b) < NEAR_ZERO, msg);
	}
	
	function checkOutOfBoundsException(obj, fn, arg1) {
		var caughtException = false;
		try {
			obj[fn](arg1); 
		}
		catch(e) {
			if (e.code == 1) {
				caughtException = true;
			}
		}
		ok(caughtException, 'Caugh an INDEX_SIZE_ERR exception');
	}

	function setUp() {
		svgcontent = svgroot.appendChild(document.createElementNS(svgns, 'svg'));
		rect = svgcontent.appendChild(document.createElementNS(svgns, 'rect'));
		rect.id = 'r';
		circle = svgcontent.appendChild(document.createElementNS(svgns, 'circle'));
		circle.id = 'c';
	}
	
	function tearDown() {
		svgedit.transformlist.resetListMap();
		while (svgroot.hasChildNodes()) {
			svgroot.removeChild(svgroot.firstChild);
		}
	}

	module('svgedit.svgtransformlist');

	test('Test svgedit.transformlist package', function() {
		expect(2);
		
		ok(svgedit.transformlist);
		ok(svgedit.transformlist.getTransformList);
	});

	test('Test svgedit.transformlist.getTransformList() function', function() {
		expect(4);
		setUp();
		
		var rxform = svgedit.transformlist.getTransformList(rect);
		var cxform = svgedit.transformlist.getTransformList(circle);
		
		ok(rxform);
		ok(cxform);
		equals(typeof rxform, typeof {});
		equals(typeof cxform, typeof {});
		
		tearDown();
	});

	test('Test SVGTransformList.numberOfItems property', function() {
		expect(2);
		setUp();
		
		var rxform = svgedit.transformlist.getTransformList(rect);
		
		equals(typeof rxform.numberOfItems, typeof 0);
		equals(rxform.numberOfItems, 0);
		
		tearDown();
	});

	test('Test SVGTransformList.initialize()', function() {
		expect(6);
		setUp();
		
		var rxform = svgedit.transformlist.getTransformList(rect);
		var cxform = svgedit.transformlist.getTransformList(circle);
		
		var t = svgcontent.createSVGTransform();
		ok(t);
		ok(rxform.initialize);
		equals(typeof rxform.initialize, typeof function(){});
		rxform.initialize(t);
		equals(rxform.numberOfItems, 1);
		equals(cxform.numberOfItems, 0);

		// If a transform was already in a transform list, this should
		// remove it from its old list and add it to this list.
		cxform.initialize(t);
		// This also fails in Firefox native.
//		equals(rxform.numberOfItems, 0, 'Did not remove transform from list before initializing another transformlist');
		equals(cxform.numberOfItems, 1);
		
		tearDown();
	});

	test('Test SVGTransformList.appendItem() and getItem()', function() {
		expect(12);
		setUp();
		
		var rxform = svgedit.transformlist.getTransformList(rect);
		var cxform = svgedit.transformlist.getTransformList(circle);
		
		var t1 = svgcontent.createSVGTransform(),
			t2 = svgcontent.createSVGTransform(),
			t3 = svgcontent.createSVGTransform();
		
		ok(rxform.appendItem);
		ok(rxform.getItem);
		equals(typeof rxform.appendItem, typeof function(){});
		equals(typeof rxform.getItem, typeof function(){});

		rxform.appendItem(t1);
		rxform.appendItem(t2);
		rxform.appendItem(t3);
		
		equals(rxform.numberOfItems, 3);
		var rxf = rxform.getItem(0);
		equals(rxf, t1);
		equals(rxform.getItem(1), t2);
		equals(rxform.getItem(2), t3);

		checkOutOfBoundsException(rxform, 'getItem', -1);
		checkOutOfBoundsException(rxform, 'getItem', 3);
		
		cxform.appendItem(t1);
		// These also fail in Firefox native.
//		equals(rxform.numberOfItems, 2, 'Did not remove a transform from a list before appending it to a new transformlist');
//		equals(rxform.getItem(0), t2, 'Found the wrong transform in a transformlist');
//		equals(rxform.getItem(1), t3, 'Found the wrong transform in a transformlist');

		equals(cxform.numberOfItems, 1);
		equals(cxform.getItem(0), t1);
		
		tearDown();
	});

	test('Test SVGTransformList.removeItem()', function() {
		expect(7);
		setUp();
		
		var rxform = svgedit.transformlist.getTransformList(rect);
		
		var t1 = svgcontent.createSVGTransform(),
			t2 = svgcontent.createSVGTransform();
		ok(rxform.removeItem);
		equals(typeof rxform.removeItem, typeof function(){});
		rxform.appendItem(t1);
		rxform.appendItem(t2);
		
		var removedTransform = rxform.removeItem(0);
		equals(rxform.numberOfItems, 1);
		equals(removedTransform, t1);
		equals(rxform.getItem(0), t2);
		
		checkOutOfBoundsException(rxform, 'removeItem', -1);
		checkOutOfBoundsException(rxform, 'removeItem', 1);
		
		tearDown();
	});

	test('Test SVGTransformList.replaceItem()', function() {
		expect(8);
		setUp();
		
		var rxform = svgedit.transformlist.getTransformList(rect);
		var cxform = svgedit.transformlist.getTransformList(circle);
		
		ok(rxform.replaceItem);
		equals(typeof rxform.replaceItem, typeof function(){});

		var t1 = svgcontent.createSVGTransform(),
			t2 = svgcontent.createSVGTransform(),
			t3 = svgcontent.createSVGTransform();
		
		rxform.appendItem(t1);
		rxform.appendItem(t2);
		cxform.appendItem(t3);
		
		var newItem = rxform.replaceItem(t3, 0);
		equals(rxform.numberOfItems, 2);
		equals(newItem, t3);
		equals(rxform.getItem(0), t3);
		equals(rxform.getItem(1), t2);
		// Fails in Firefox native
//		equals(cxform.numberOfItems, 0);
		
		// test replaceItem within a list
		rxform.appendItem(t1);
		rxform.replaceItem(t1, 0);
		// Fails in Firefox native
//		equals(rxform.numberOfItems, 2);
		equals(rxform.getItem(0), t1);
		equals(rxform.getItem(1), t2);
		
		tearDown();
	});

	test('Test SVGTransformList.insertItemBefore()', function() {
		expect(10);
		setUp();
		
		var rxform = svgedit.transformlist.getTransformList(rect);
		var cxform = svgedit.transformlist.getTransformList(circle);
		
		ok(rxform.insertItemBefore);
		equals(typeof rxform.insertItemBefore, typeof function(){});

		var t1 = svgcontent.createSVGTransform(),
			t2 = svgcontent.createSVGTransform(),
			t3 = svgcontent.createSVGTransform();
		
		rxform.appendItem(t1);
		rxform.appendItem(t2);
		cxform.appendItem(t3);
		
		var newItem = rxform.insertItemBefore(t3, 0);
		equals(rxform.numberOfItems, 3);
		equals(newItem, t3);
		equals(rxform.getItem(0), t3);
		equals(rxform.getItem(1), t1);
		equals(rxform.getItem(2), t2);
		// Fails in Firefox native
//		equals(cxform.numberOfItems, 0);

		rxform.insertItemBefore(t2, 1);
		// Fails in Firefox native (they make copies of the transforms)
//		equals(rxform.numberOfItems, 3);
		equals(rxform.getItem(0), t3);
		equals(rxform.getItem(1), t2);
		equals(rxform.getItem(2), t1);
		tearDown();
	});

	test('Test SVGTransformList.init() for translate(200,100)', function() {
		expect(8);
		setUp();
		rect.setAttribute('transform', 'translate(200,100)');

		var rxform = svgedit.transformlist.getTransformList(rect);
		equals(1, rxform.numberOfItems);

		var translate = rxform.getItem(0);
		equals(translate.type, 2);

		var m = translate.matrix;
		equals(m.a, 1);
		equals(m.b, 0);
		equals(m.c, 0);
		equals(m.d, 1);
		equals(m.e, 200);
		equals(m.f, 100);

		tearDown();
	});

	test('Test SVGTransformList.init() for scale(4)', function() {
		expect(8);
		setUp();
		rect.setAttribute('transform', 'scale(4)');

		var rxform = svgedit.transformlist.getTransformList(rect);
		equals(1, rxform.numberOfItems);

		var scale = rxform.getItem(0);
		equals(3, scale.type);

		var m = scale.matrix;
		equals(m.a, 4);
		equals(m.b, 0);
		equals(m.c, 0);
		equals(m.d, 4);
		equals(m.e, 0);
		equals(m.f, 0);

		tearDown();
	});

	test('Test SVGTransformList.init() for scale(4,3)', function() {
		expect(8);
		setUp();
		rect.setAttribute('transform', 'scale(4,3)');

		var rxform = svgedit.transformlist.getTransformList(rect);
		equals(1, rxform.numberOfItems);

		var scale = rxform.getItem(0);
		equals(3, scale.type);

		var m = scale.matrix;
		equals(m.a, 4);
		equals(m.b, 0);
		equals(m.c, 0);
		equals(m.d, 3);
		equals(m.e, 0);
		equals(m.f, 0);

		tearDown();
	});

	test('Test SVGTransformList.init() for rotate(45)', function() {
		expect(9);
		setUp();
		rect.setAttribute('transform', 'rotate(45)');

		var rxform = svgedit.transformlist.getTransformList(rect);
		equals(1, rxform.numberOfItems);

		var rotate = rxform.getItem(0);
		equals(4, rotate.type);
		equals(45, rotate.angle);

		var m = rotate.matrix;
		almostEquals(m.a, 1/Math.sqrt(2));
		almostEquals(m.b, 1/Math.sqrt(2));
		almostEquals(m.c, -1/Math.sqrt(2));
		almostEquals(m.d, 1/Math.sqrt(2));
		equals(m.e, 0);
		equals(m.f, 0);

		tearDown();
	});

	test('Test SVGTransformList.init() for rotate(45, 100, 200)', function() {
		expect(9);
		setUp();
		rect.setAttribute('transform', 'rotate(45, 100, 200)');

		var rxform = svgedit.transformlist.getTransformList(rect);
		equals(1, rxform.numberOfItems);

		var rotate = rxform.getItem(0);
		equals(4, rotate.type);
		equals(45, rotate.angle);

		var m = rotate.matrix;
		almostEquals(m.a, 1/Math.sqrt(2));
		almostEquals(m.b, 1/Math.sqrt(2));
		almostEquals(m.c, -1/Math.sqrt(2));
		almostEquals(m.d, 1/Math.sqrt(2));

		var r = svgcontent.createSVGMatrix();
		r.a = 1/Math.sqrt(2); r.b = 1/Math.sqrt(2);
		r.c = -1/Math.sqrt(2); r.d = 1/Math.sqrt(2);

		var t = svgcontent.createSVGMatrix();
		t.e = -100; t.f = -200;

		var t_ = svgcontent.createSVGMatrix();
		t_.e = 100; t_.f = 200;
		
		var result = t_.multiply(r).multiply(t);
		
		almostEquals(m.e, result.e);
		almostEquals(m.f, result.f);

		tearDown();
	});
	
	test('Test SVGTransformList.init() for matrix(1, 2, 3, 4, 5, 6)', function() {
		expect(8);
		setUp();
		rect.setAttribute('transform', 'matrix(1,2,3,4,5,6)');

		var rxform = svgedit.transformlist.getTransformList(rect);
		equals(1, rxform.numberOfItems);

		var mt = rxform.getItem(0);
		equals(1, mt.type);

		var m = mt.matrix;
		equals(m.a, 1);
		equals(m.b, 2);
		equals(m.c, 3);
		equals(m.d, 4);
		equals(m.e, 5);
		equals(m.f, 6);

		tearDown();
	});

  }); 
  </script>  
</head>  
<body>  
  <h1 id='qunit-header'>Unit Tests for svgtransformlist.js</h1>
  <h2 id='qunit-banner'></h2>
  <h2 id='qunit-userAgent'></h2>
  <ol id='qunit-tests'>
  </ol>
  <div id='svgroot' style='visibility:hidden'></div>
</body>  
</html>
